package dao

import (
	"context"
	"errors"

	"bmember/pkg/util"

	"bmember/internal/model"
	"bmember/pkg/db/pgex"
)

// LoginChannelDao 登陆渠道相关
type LoginChannelDao interface {
	// GetMemberByOpenid 根据 openid 获取用户渠道
	GetMemberByOpenid(ctx context.Context, brandId int64, openId, appId string, channel int8) (*model.LoginChannel, error)
	// GetMemberByUnionId 根据 union_id 获取用户渠道
	GetMemberByUnionId(ctx context.Context, brandId int64, unionId string) ([]*model.LoginChannel, error)
	// CreateLoginChannel 创建用户渠道
	CreateLoginChannel(ctx context.Context, ch *model.LoginChannel) (int64, error)
	// UpdateLoginChannelById 更新登陆 channel
	UpdateLoginChannelById(ctx context.Context, ch *model.LoginChannel) error
	// UpdateLoginChannelMember 变更渠道会员
	UpdateLoginChannelMember(ctx context.Context, brandId, oMemberId, tMemberId int64) error
	// GetOpenIdByMemberApp 获取渠道信息 by memberId, channel
	GetOpenIdByMemberApp(ctx context.Context, memberId int64, app int8) ([]*model.LoginChannel, error)
	// GetRelatedMemberId 获取关联的会员id，由于会员合并造成
	GetRelatedMemberId(ctx context.Context, brandId, memberId int64) ([]int64, error)
}

type chDaoImpl struct {
	*DaoBase
	name string
}

var chDao LoginChannelDao

// InitLoginChannelDao 初始化 login channel dao 层
func InitLoginChannelDao() {
	chDao = &chDaoImpl{
		DaoBase: daoBase,
		name:    "dao_login_channel",
	}
}

// GetLoginChannelDao 获取  login channel dao
func GetLoginChannelDao() LoginChannelDao {
	return chDao
}

// GetMemberByOpenid 根据 open_id 获取用户渠道
func (dao *chDaoImpl) GetMemberByOpenid(ctx context.Context, brandId int64, openId, appId string, channel int8) (*model.LoginChannel, error) {
	query := "SELECT * FROM login_channel WHERE brand_id=? AND app_id=? AND open_id=? AND channel=? AND deleted_at=0"
	ch := &model.LoginChannel{}
	err := dao.db.Get(ctx, ch, query, brandId, appId, openId, channel)
	if errors.Is(err, pgex.ErrEmpty) {
		return nil, nil
	}
	return ch, err
}

// GetMemberByUnionId 根据 union_id 获取用户渠道
func (dao *chDaoImpl) GetMemberByUnionId(ctx context.Context, brandId int64, unionId string) ([]*model.LoginChannel, error) {
	query := "SELECT * FROM login_channel WHERE brand_id=? AND union_id=? AND deleted_at=0"
	var channels []*model.LoginChannel
	err := dao.db.Query(ctx, &channels, query, brandId, unionId)
	return channels, err
}

// CreateLoginChannel 创建用户渠道
func (dao *chDaoImpl) CreateLoginChannel(ctx context.Context, ch *model.LoginChannel) (int64, error) {
	if ch == nil {
		return 0, nil
	}
	param := []interface{}{
		ch.BrandId,
		ch.MemberId,
		ch.RegMemberId,
		ch.OpenId,
		ch.UnionId,
		ch.AppId,
		ch.Nickname,
		ch.Avatar,
		ch.Channel,
		ch.Ext,
		ch.CreatedAt,
		ch.UpdatedAt,
	}
	query := "INSERT INTO login_channel (brand_id, member_id, reg_member_id, open_id, union_id, app_id, nickname, avatar, " +
		"channel, ext, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"
	aff, err := dao.db.PgExec(ctx, "id", query, param...)
	if err != nil {
		return 0, err
	}
	lastId, _ := aff.GetLastId()
	return lastId, nil
}

// UpdateLoginChannelById 更新登陆 channel
func (dao *chDaoImpl) UpdateLoginChannelById(ctx context.Context, ch *model.LoginChannel) error {
	if ch == nil {
		return nil
	}
	param := []interface{}{
		ch.OpenId,
		ch.UnionId,
		ch.AppId,
		ch.Avatar,
		ch.Channel,
		ch.Ext,
		ch.Id,
	}
	query := "UPDATE login_channel SET open_id=?, union_id=?, app_id=?, avatar=?, channel=?, status=?, " +
		"ext=? WHERE id=?"
	_, err := dao.db.Update(ctx, query, param...)
	return err
}

// UpdateLoginChannelMember 变更渠道会员
func (dao *chDaoImpl) UpdateLoginChannelMember(ctx context.Context, brandId, oMemberId, tMemberId int64) error {
	query := "UPDATE login_channel SET member_id=?, updated_at=? WHERE brand_id=? AND member_id=? AND deleted_at=0"
	_, err := dao.db.Update(ctx, query, tMemberId, util.GetNow(), brandId, oMemberId)
	return err
}

// GetOpenIdByMemberApp 获取渠道信息 by memberId, channel
func (dao *chDaoImpl) GetOpenIdByMemberApp(ctx context.Context, memberId int64, app int8) ([]*model.LoginChannel, error) {
	query := "SELECT brand_id, member_id, open_id, app_id FROM login_channel WHERE member_id=? AND channel=? " +
		"AND deleted_at=0 ORDER BY updated_at DESC"
	var channels []*model.LoginChannel
	err := dao.db.Query(ctx, &channels, query, memberId, app)
	return channels, err
}

// GetRelatedMemberId 获取关联的会员id，由于会员合并造成
func (dao *chDaoImpl) GetRelatedMemberId(ctx context.Context, brandId, memberId int64) ([]int64, error) {
	var memIds []int64
	query := "SELECT DISTINCT(reg_member_id) FROM login_channel WHERE brand_id=? AND member_id=?"
	err := dao.db.Query(ctx, &memIds, query, brandId, memberId)
	return memIds, err
}
